package it.antonio.ilpizze.ioc.builders;

import it.antonio.ilpizze.ioc.Builder;
import it.antonio.ilpizze.ioc.Decoration;
import it.antonio.ilpizze.ioc.Dependencies;
import it.antonio.ilpizze.ioc.InjectionMonitor;
import it.antonio.ilpizze.ioc.ListDef;
import it.antonio.ilpizze.ioc.Scope;
import java.util.ArrayList;
import java.util.List;

public class ListBuilder implements Builder<List<?>>{
	
	private Object key;
	private ListDef config;
	
	private Scope<List<? super Object>> scope;
	private List<Decoration<List<? super Object>>> decorations;
	private List<InjectionMonitor> monitors;
	
	public ListBuilder(Object key, ListDef config, Scope<List<? super Object>> scope, List<Decoration<List<? super Object>>> decorations, List<InjectionMonitor> monitors) {
		this.key = key;
		this.config = config;
		this.scope = scope;
		this.decorations = decorations;
		this.monitors = monitors;
	}

	@Override
	public Object getKey() {
		return key;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Class<? extends List<?>> getType() {
		return (Class<? extends List<?>>) List.class;
	}

	@Override
	public List<?> build(Dependencies dependencies) {
		for(InjectionMonitor monitor: monitors){
			monitor.before(getKey(),getType());
		}
		
		List<? super Object> list = scope.get();
		if(list != null){
			return list;
		} else {
			list = new ArrayList<Object>();
			for(Object key: config){
				Object instance = dependencies.get(key); 
				list.add(instance);
			}
			for (Decoration<List<? super Object>> decoration : decorations) {
				decoration.decorate(list, dependencies);
			}
			scope.set(list);
		}
		for(InjectionMonitor monitor: monitors){
			monitor.after(getKey(),getType());
		}
		
		return list;
	}

}
